/**
 * @(#)GruppenkalenderVerwaltungImpl.java
 * 1.0, 2013-01-24
 */
package de.hdm.gruppenkalender.team04;

import de.hdm.gruppenkalender.team04.data.Alarm;
import de.hdm.gruppenkalender.team04.data.AlarmImpl;
import de.hdm.gruppenkalender.team04.data.Kalender;
import de.hdm.gruppenkalender.team04.data.KalenderImpl;
import de.hdm.gruppenkalender.team04.data.Kalendereintrag;
import de.hdm.gruppenkalender.team04.data.Kategorie;
import de.hdm.gruppenkalender.team04.data.KategorieImpl;
import de.hdm.gruppenkalender.team04.data.Person;
import de.hdm.gruppenkalender.team04.data.PersonImpl;
import de.hdm.gruppenkalender.team04.data.Termin;
import de.hdm.gruppenkalender.team04.data.Wiederholung;
import de.hdm.gruppenkalender.team04.data.WiederholungImpl;
import de.hdm.gruppenkalender.team04.db.AlarmMapper;
import de.hdm.gruppenkalender.team04.db.KalenderMapper;
import de.hdm.gruppenkalender.team04.db.KalenderZugriffMapper;
import de.hdm.gruppenkalender.team04.db.KalendereintragMapper;
import de.hdm.gruppenkalender.team04.db.KategorieMapper;
import de.hdm.gruppenkalender.team04.db.PersonMapper;
import de.hdm.gruppenkalender.team04.db.TerminMapper;
import de.hdm.gruppenkalender.team04.db.TerminTeilnahmeMapper;
import de.hdm.gruppenkalender.team04.db.WiederholungMapper;
import de.hdm.gruppenkalender.team04.gui.DialogTermin;
import de.hdm.gruppenkalender.team04.report.BerichtGenerator;
import de.hdm.gruppenkalender.team04.report.BerichtGeneratorImpl;
import java.rmi.RemoteException;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Implementierungsklasse der Schnittstelle {@link GruppenkalenderVerwaltung}.
 *
 * @author Mathias Bendel (mb167)
 * @author Björn Fichnter (bf023)
 * @author Stefan Hettich (sh176)
 * @author René Kugel (rk044)
 * @author Mark Leonberger (ml072)
 * @author Marta Przybylski (mp070)
 *
 * @version 1.0, 2013-01-24
 *
 * @see GruppenkalenderVerwaltung
 *
 */
// <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
// #[regen=yes,id=DCE.67054D33-DFDD-B6B3-E3A3-7D31920831FE]
// </editor-fold> 
public class GruppenkalenderVerwaltungImpl extends java.rmi.server.UnicastRemoteObject
        implements GruppenkalenderVerwaltung {

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.BC1629AB-EF40-CA7A-0E09-387F3C6C7443]
    // </editor-fold>
    private AlarmMapper alarmMapper;
    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.12238517-96B0-C8AF-5D0A-FAF9323560C0]
    // </editor-fold> 
    private KalendereintragMapper kalendereintragMapper;
    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.78777E7E-2612-75C6-36BB-28553EF21E76]
    // </editor-fold> 
    private KalenderMapper kalenderMapper;
    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.040063BD-BCD7-7788-3E23-C6156D1CB03D]
    // </editor-fold> 
    private KategorieMapper kategorieMapper;
    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.497ECAF7-E8D2-F49A-C780-3ABB4C951CDA]
    // </editor-fold> 
    private PersonMapper personMapper;
    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.BEFF6721-5859-B72D-6042-6B6FEEF9C48A]
    // </editor-fold> 
    private TerminMapper terminMapper;
    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.A91E48BC-84E7-B338-C8D0-1D139A29F895]
    // </editor-fold> 
    private WiederholungMapper wiederholungMapper;
    private TerminTeilnahmeMapper terminTeilnahmeMapper;
    private KalenderZugriffMapper kalenderZugriffMapper;
    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.A76ABBB9-1F02-6A57-8D6B-A8F12A6E837C]
    // </editor-fold> 
    private BerichtGenerator berichtGenerator;

    /**
     * Konstruktor mit allen Mappern (Alarm, Kalender, Kalendereintrag,
     * Kategorie, Person, Termin, Wiederholung).
     *
     * @param alarmMapper
     * @param kalendereintragMapper
     * @param kalenderMapper
     * @param kategorieMapper
     * @param personMapper
     * @param terminMapper
     * @param wiederholungMapper
     * @throws RemoteException
     */
    public GruppenkalenderVerwaltungImpl(AlarmMapper alarmMapper,
            KalendereintragMapper kalendereintragMapper,
            KalenderMapper kalenderMapper, KategorieMapper kategorieMapper,
            PersonMapper personMapper, TerminMapper terminMapper,
            WiederholungMapper wiederholungMapper,
            TerminTeilnahmeMapper terminTeilnahmeMapper,
            KalenderZugriffMapper kalenderZugriffMapper) throws RemoteException {
        super();
        this.alarmMapper = alarmMapper;
        this.kalendereintragMapper = kalendereintragMapper;
        this.kalenderMapper = kalenderMapper;
        this.kategorieMapper = kategorieMapper;
        this.personMapper = personMapper;
        this.terminMapper = terminMapper;
        this.wiederholungMapper = wiederholungMapper;
        this.terminTeilnahmeMapper = terminTeilnahmeMapper;
        this.kalenderZugriffMapper = kalenderZugriffMapper;

        this.berichtGenerator = new BerichtGeneratorImpl(this);
    }

    /**
     * Gibt den Bericht-Generator der Verwaltung zurück.
     *
     * @return  berichtGenerator
     */
    public BerichtGenerator getBerichtGenerator() throws RemoteException {
        return berichtGenerator;
    }

    /**
     * Setzt den Bericht-Generator der Verwaltung.
     *
     * @param   berichtGenerator der gesetzt werden soll.
     */
    public void setBerichtGenerator(BerichtGenerator berichtGenerator) throws
            RemoteException {
        this.berichtGenerator = berichtGenerator;
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.C4507B78-B539-A535-C5F7-FB8CA16D03D0]
    // </editor-fold>
    /**
     * Methode, um eine Person zu erstellen.
     *
     * Es wird ein neues Personen-Objekt angelegt,
     * dem entsprechende Attributwerte und eine ID  zugewiesen werden.
     *
     * Daraufhin wird das - mit Hilfe der in der PersonMapper-Klasse
     * implementierten Methode einfuegen abgelegt.
     *
     * @param   vorname     Vorname
     * @param   nachname    Nachname
     * @param   raum        Raum
     * @param   telefon     Telefon-Nummer
     * @param   email       Email-Adresse
     * @return  Person      die abgelegte Person
     * @throws  RemoteException
     */
    public Person erstellePerson(String vorname, String nachname, String raum,
            String telefon, String email) throws RemoteException {
        Person person = new PersonImpl();

        person.setNachname(nachname);
        person.setVorname(vorname);
        person.setRaum(raum);
        person.setTelefon(telefon);
        person.setEmail(email);

        person.setPersonId(1);
        //Person-Objekt in Datenbank ablegen
        return this.personMapper.einfuegen(person);
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.5A08C024-3C89-1309-4DB6-DF0361A4F588]
    // </editor-fold>
    /**
     * Methode, um einen Kalender zu erstellen.
     *
     * Es wird ein neues Kalender-Objekt angelegt,
     * dem entsprechende Attributwerte und eine ID zugewiesen werden.
     *
     * Daraufhin wird das Kalender-Objekt mit Hilfe der in der
     * KalenderMapper-Klasse implementierten Methode einfuegen abgelegt.
     *
     * @param   bezeichnung
     * @param   besitzerId
     * @param   zugriffsberechtigteId
     * @return  Kalender                der erstellte Kalender
     * @throws  RemoteException
     */
    public Kalender erstelleKalender(String bezeichnung, int besitzerId,
            Vector<Integer> zugriffsberechtigteId) throws RemoteException {
        Kalender kalender = new KalenderImpl();

        kalender.setBezeichnung(bezeichnung);
        kalender.setBesitzerId(besitzerId);
        kalender.setZugriffsberechtigteId(zugriffsberechtigteId);

        kalender.setKalenderId(1);
        //Kalender-Objekt in Datenbank ablegen
        kalender = this.kalenderMapper.einfuegen(kalender);
        if (kalender == null) {
            System.out.println("null");
        } else {
            System.out.println("ok");
        }
        for (int personId : zugriffsberechtigteId) {
            this.kalenderZugriffMapper.einfuegen(kalender.getKalenderId(),
                    personId);
        }

        return kalender;
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.FB68FCB1-95C2-6881-530C-D3E2A6215181]
    // </editor-fold>
    /**
     * Methode, um eine Kategorie zu erstellen.
     *
     * Es wird ein neues Kategorie-Objekt angelegt,
     * dem der Name und eine ID zugewiesen werden.
     *
     * Daraufhin wird das Kategorie-Objekt mit Hilfe der in der 
     * KategorieMapper-Klasse implementierten Methode einfuegen abgelegt.
     *
     * @param   name        Name
     * @return  Kategorie   die abgelegte Kategorie.
     * @throws  RemoteException
     */
    public Kategorie erstelleKategorie(String name) throws RemoteException {
        Kategorie kategorie = new KategorieImpl();

        kategorie.setName(name);

        kategorie.setKategorieId(0);
        //Kategorie-Objekt in Datenbank ablegen
        return this.kategorieMapper.einfuegen(kategorie);
    }

    /**
     * Erstellt einen übergebenen Termin und ggf. einen Alarm und mehrere
     * Wiederholungen.
     *
     * @param   start                   Start-Zeitpunkt
     * @param   ende                    End-Zeitpunkt
     * @param   titel                   Titel
     * @param   ort                     Ort
     * @param   beschreibung            Beschreibung
     * @param   kategorieId             Kategorie-Id einer zugehörigen {@link Kategorie}
     * @param   erstellerId             Ersteller-Id einer zugehörigen {@link Person}
     * @param   kalenderId              Kalender-Id eines zugehörigen {@link Kalender}
     * @param   teilnehmerId            Teilnehmer-Ids zugehörigeer {@link Person}en
     * @param   alarmStart              Start-Zeitpunkt des zugehörigen {@link Alarm}
     * @param   anzahlWiederholungen    Anzahl der Wiederholungen
     * @param   abstandWiederholungen   Abstand zwischen den Wiederholungen
     * @throws  RemoteException
     */
    public void erstelleTermine(Timestamp start, Timestamp ende, String titel,
            String ort, String beschreibung, int kategorieId, int erstellerId,
            int kalenderId, Vector<Integer> teilnehmerId, Timestamp alarmStart,
            int anzahlWiederholungen, int abstandWiederholungen) throws
            RemoteException {

        System.out.println(anzahlWiederholungen);
        // Calendar-Instance zu berechnen der Start- und Enddaten.
        Calendar c = Calendar.getInstance();

        int folgeterminId = 0;
        Wiederholung wiederholung = new WiederholungImpl();
        wiederholung.setTitel(titel);
        wiederholung.setOrt(ort);
        wiederholung.setBeschreibung(beschreibung);
        wiederholung.setKategorieId(kategorieId);
        wiederholung.setErstellerId(erstellerId);
        wiederholung.setKalenderId(kalenderId);

        for (int i = anzahlWiederholungen; i > 0; i--) {
            // Startdatum berechen.
            c.setTime(start);
            c.add(abstandWiederholungen, i - 1);
            Timestamp tempStart = new Timestamp(c.getTime().getTime());
            wiederholung.setStart(tempStart);

            // Enddatum berechnen.
            c.setTime(ende);
            c.add(abstandWiederholungen, i - 1);
            Timestamp tempEnde = new Timestamp(c.getTime().getTime());
            wiederholung.setEnde(tempEnde);

            kalendereintragMapper.einfuegen((Kalendereintrag) wiederholung);
            wiederholung.setFolgeterminId(folgeterminId);
            terminMapper.einfuegen((Termin) wiederholung);

            if (i > 1) {
                wiederholungMapper.einfuegen(wiederholung);
            }

            folgeterminId = wiederholung.getId();

            for (int teilnehmer : teilnehmerId) {
                terminTeilnahmeMapper.einfuegen(teilnehmer, wiederholung.getId());
            }

            if (alarmStart != null) {
                // Es soll ein Alarm angelegt werden.
                c.setTime(alarmStart);
                c.add(abstandWiederholungen, i - 1);
                Timestamp tempAlarmStart = new Timestamp(c.getTime().getTime());

                Alarm alarm = new AlarmImpl();
                alarm.setStart(tempAlarmStart);
                alarm.setEnde(null);
                alarm.setTitel("Erinnerung");
                alarm.setOrt("");
                alarm.setBeschreibung("");
                alarm.setKategorieId(kategorieId);
                alarm.setErstellerId(erstellerId);
                alarm.setKalenderId(kalenderId);
                // eventuell hier Teilnahmen anfügen.
                kalendereintragMapper.einfuegen((Kalendereintrag) alarm);

                terminMapper.einfuegen((Termin) alarm);
                alarm.setGueltigFuerId(wiederholung.getId());
                alarmMapper.einfuegen(alarm);
            }
        }
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.CB536206-DD94-8B67-6B18-8BAE52727245]
    // </editor-fold>
    /**
     * Methode, um einen Alarm zu erstellen.
     *
     * Es wird ein neues Alarm-Objekt angelegt,
     * dem entsprechende Attributwerte zugewiesen werden.
     * Die ID wird zwecks Vererbungshierarchie vom Termin geholt.
     *
     * Daraufhin wird das Termin-Objekt mit Hilfe der in der
     * Terminmapper-Klasse implementierten Methode einfuegen abgelegt.
     *
     * @param start             Start-Zeitpunkt
     * @param titel             Titel
     * @param kategoreiId       Kategore-Id einer zugehörigen {@link Kategorie}
     * @param erstellerId       Ersteller-Id einer zugehörigen {@link Person}
     * @param kalenderId        Termin-Id eines verknüpften Folge-{@link Termin}
     * @param gueltigFuerId     Termin-Id eines zugeordneten {@link Termin}
     * @return Alarm            der abgelegte Alarm
     * @throws RemoteException
     */
    public Alarm erstelleAlarm(Timestamp start, String titel, int kategoreiId,
            int erstellerId, int kalenderId, int gueltigFuerId) throws
            RemoteException {

        Alarm alarm = new AlarmImpl();

        alarm.setStart(start);
        alarm.setEnde(null);
        alarm.setTitel(titel);
        alarm.setOrt("");
        alarm.setBeschreibung("");
        alarm.setKategorieId(kategoreiId);
        alarm.setErstellerId(erstellerId);
        alarm.setKalenderId(kalenderId);
        alarm.setFolgeterminId(0);
        alarm.setGueltigFuerId(gueltigFuerId);

        /**
         * Notwendig, um Verknüpfung zwischen Termin und Alarm
         * herzustellen.
         * @TODO Wichtig für Mapper! Kein Überschreiben, sondern diese Id nehmen!
         */
        alarm.setId(1);
        //Alarm-Objekt in Datenbank ablegen
        this.kalendereintragMapper.einfuegen((Kalendereintrag) alarm);
        this.terminMapper.einfuegen((Termin) alarm);
        return this.alarmMapper.einfuegen(alarm);
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.0AB2D722-4123-8E70-FEA1-8E0DA2EA1D50]
    // </editor-fold>
    /**
     * Methode, um ein Personen-Objekt zu löschen. 
     * 
     * Es wird die PersonMapper-Klasse aufgerufen,
     * um den Datenbankeintrag löschen zu können.
     *
     * @param   person
     * @throws  RemoteException
     */
    public void loeschePerson(Person person) throws RemoteException {
        this.personMapper.loeschen(person);
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.0E8EBE9B-C87B-8AE0-483B-4DF58BFF7AED]
    // </editor-fold>
    /**
     * Methode, um ein Kalender-Objekt zu löschen. 
     * 
     * Es wird die KalenderMapper-Klasse aufgerufen,
     * um den Datenbankeintrag löschen zu können.
     *
     * @param   kalender
     * @throws  RemoteException
     */
    public void loescheKalender(Kalender kalender) throws RemoteException {
        this.kalenderMapper.loeschen(kalender);
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.06C9919B-EC8B-85E5-631A-5ACB2AC66118]
    // </editor-fold>
    /**
     * Methode, um ein Kategorie-Objekt zu löschen. 
     * 
     * Es wird die KategorieMapper-Klasse aufgerufen,
     * um den Datenbankeintrag löschen zu können.
     *
     * @param   kategorie
     * @throws  RemoteException
     */
    public void loescheKategorie(Kategorie kategorie) throws RemoteException {
        this.kategorieMapper.loeschen(kategorie);
    }

    /**
     * Methode, um ein Termin-Objekt und ggf. dessen Wiederholungn zu löschen.
     *
     * Es wird die TerminMapper-Klasse, die Kalendereintrag-Klasse,
     * die AlarmMapper-Klasse, sowie die WiederholungMapper-Klasse aufgerufen,
     * um den Datenbankeintrag löschen zu können.
     *
     * @param termin            {@link Termin} der gelöscht werden soll
     * @param nutzer            {@link Person} die diesen Termin löschen möchte
     * @param allesLoeschen     Entscheidung, ob alle Termine, oder nur dieser Termin gelöscht werden soll.
     * @throws RemoteException
     */
    public void loescheTermin(Termin termin, Person nutzer,
            boolean allesLoeschen) throws RemoteException {
        if (allesLoeschen) {
            // Es sollen alle Wiederholung gelöscht werden.
            Termin tempTermin = termin;
            while (istWiederholung(tempTermin.getId())) {
                /**
                 * Ausgewählter Termin ist Wiederholung, deshalb
                 * zunächst inital Termin suchen.
                 */
                tempTermin =
                        terminMapper.findeViaFolgetermin(tempTermin.getId());
            }

            // Nun ist der Initial-Termin auf jeden Fall gefunden.
            int terminId = tempTermin.getId();
            Vector<Integer> zuLoeschendeTermine = new Vector<Integer>();

            while (terminId != 0) {
                // So lange es Folgetermine gibt.
                zuLoeschendeTermine.add(terminId);
                tempTermin = terminMapper.findeViaSchluessel(tempTermin.
                        getFolgeterminId());
                if (tempTermin != null) {
                    terminId = tempTermin.getId();
                } else {
                    break;
                }
            }

            if (nutzer == null || nutzer.getPersonId() ==
                    termin.getErstellerId()) {
                // Nutzer ist entweder Admin, oder Ersteller.
                // Die komplette Liste der Termine/Wiederholung durchlaufen.
                for (int i : zuLoeschendeTermine) {
                    // Prüfen, ob es einen Alarm gibt, ggf. diesen löschen.
                    Vector<Alarm> alarme = alarmMapper.findeViaGueltigFuer(i);
                    for (Alarm a : alarme) {
                        // TODO: Entscheidung Alarm Sichtbarkeit!
                        // Nur wenn alle Teilnehmer auch Erinnerung sehen.
                        //kalenderZugriffMapper.loeschenViaTermin(a.getId());
                        kalendereintragMapper.loeschen(a.getId());
                        terminMapper.loeschen(a.getId());
                        alarmMapper.loeschen(a);
                    }

                    // Prüfen, ob es eine Wiederholung, ggf. diese löschen.
                    if (istWiederholung(i)) {
                        wiederholungMapper.loeschen(i);
                    }
                    kalendereintragMapper.loeschen(i);
                    terminTeilnahmeMapper.loeschenViaTermin(i);
                    terminMapper.loeschen(i);
                }
            } else {
                // Nutzer ist Teilnehmer.
                // Die komplette Liste der Termine/Wiederholung durchlaufen.
                for (int i : zuLoeschendeTermine) {
                    // Alarme nur für Person löschen.
                    Vector<Alarm> alarme = alarmMapper.findeViaGueltigFuer(i);
                    for (Alarm a : alarme) {
                        Kalendereintrag k =
                                kalendereintragMapper.findeViaSchluessel(
                                a.getId());
                        if (k.getErstellerId() == nutzer.getPersonId()) {
                            kalendereintragMapper.loeschen(a.getId());
                            terminMapper.loeschen(a.getId());
                            alarmMapper.loeschen(a);
                        }
                    }
                    terminTeilnahmeMapper.loeschen(nutzer.getPersonId(), i);
                }
            }
        } else {
            // nur einzelnen Termin löschen.
            if (nutzer == null || nutzer.getPersonId() ==
                    termin.getErstellerId()) {
                // Nutzer ist entweder Admin, oder Ersteller.
                // Es soll nur der Ausgewählte  gelöscht werden.
                Vector<Alarm> alarme = alarmMapper.findeViaGueltigFuer(termin);
                for (Alarm a : alarme) {
                    kalendereintragMapper.loeschen(a.getId());
                    terminMapper.loeschen(a.getId());
                    alarmMapper.loeschen(a);
                }

                // Folgetermin-Id zwischenspeichern.
                int folgeterminId = termin.getFolgeterminId();

                if (istWiederholung(termin.getId())) {
                    // Vorgängertermin ermitteln
                    Termin vorgaengerTermin = terminMapper.findeViaFolgetermin(
                            termin.getId());
                    // Neu-Verknüpfung der Wiederholung.
                    vorgaengerTermin.setFolgeterminId(folgeterminId);

                    terminMapper.aktualisieren(vorgaengerTermin);

                    kalendereintragMapper.loeschen(termin.getId());
                    wiederholungMapper.loeschen(termin.getId());
                    terminMapper.loeschen(termin);

                } else {
                    wiederholungMapper.loeschen(folgeterminId);

                    kalendereintragMapper.loeschen(termin.getId());
                    terminMapper.loeschen(termin);
                }
            } else {
                // Nutzer ist Teilnehmer.
                terminTeilnahmeMapper.loeschen(nutzer.getPersonId(), termin.
                        getId());
                // Alarme nur für Person löschen.
                Vector<Alarm> alarme = alarmMapper.findeViaGueltigFuer(termin);
                for (Alarm a : alarme) {
                    Kalendereintrag k =
                            kalendereintragMapper.findeViaSchluessel(a.getId());
                    if (k.getErstellerId() == nutzer.getPersonId()) {
                        kalendereintragMapper.loeschen(a.getId());
                        terminMapper.loeschen(a.getId());
                        alarmMapper.loeschen(a);
                    }
                }
            }
        }
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.8B613B3D-6263-1405-A413-9D4A485B712C]
    // </editor-fold>
    /**
     * Methode, um ein Alarm-Objekt zu löschen. 
     * 
     * Es werden die TerminMapper und die Alarmmapper-Klasse aufgerufen,
     * um den Datenbankeinträge löschen zu können.
     * Bei Ersterem wir die entsprechende Termin-ID gelöscht.
     *
     * @param   alarm
     * @throws  RemoteException
     */
    public void loescheAlarm(Alarm alarm) throws RemoteException {
        /**
         * Es muss nur der Kalendereintrag gelöscht werden,
         * Termin und Alarme werden durch die Indizes (Löschweitergabe)
         * in der Datenbank gelöscht!
         */
        this.kalendereintragMapper.loeschen(alarm.getId());
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.BA9B456A-673F-E991-5D56-6F1951220A8C]
    // </editor-fold>
    /**
     * Methode, um eine Person zu speichern.
     *
     * @param   person
     */
    public void speichern(Person person) throws RemoteException {
        this.personMapper.aktualisieren(person);
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.D5D38691-1D18-F6C0-ADE0-6F11E35B9FFA]
    // </editor-fold>
    /**
     * Methode, um ein Kalender zu speichern.
     *
     * @param   kalender
     */
    public void speichern(Kalender kalender) throws RemoteException {
        this.kalenderMapper.aktualisieren(kalender);
        this.kalenderZugriffMapper.loeschenViaKalender(kalender.getKalenderId());
        for (int personId : kalender.getZugriffsberechtigteId()) {
            this.kalenderZugriffMapper.einfuegen(kalender.getKalenderId(),
                    personId);
        }
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.2C2F4065-6B6C-5A47-AAE8-71CEE14EF084]
    // </editor-fold>
    /**
     * Methode, um ein Kategorie zu speichern.
     *
     * @param   kategorie
     */
    public void speichern(Kategorie kategorie) throws RemoteException {
        this.kategorieMapper.aktualisieren(kategorie);
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.86B3C8CD-7037-D6BA-5BAE-395C2A7FD2D8]
    // </editor-fold>
    /**
     * Methode, um einen Alarm zu speichern
     *
     * @param   alarm
     */
    public void speichern(Alarm alarm) throws RemoteException {
        this.kalendereintragMapper.aktualisieren((Kalendereintrag) alarm);
        this.alarmMapper.aktualisieren(alarm);
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.75D36973-FAAD-1097-07E2-F6A6EEE57F87]
    // </editor-fold>
    /**
     * Methode, um alle vorhandenen Personen zu ermitteln. 
     * 
     * Bei dieser Methode werden die entsprechenden
     * Daten ungefiltert aus der Datenbank geholt und ausgegeben.
     *
     * @return  Vector<Person>  mit allen Personen.
     */
    public Vector<Person> ermittleAllePersonen() throws RemoteException {
        return personMapper.findeAlle();
    }

    /**
     * Ermittelt eine Person anhand der übergebenen id.
     *
     * @param   id
     * @return  Person
     * @throws  RemoteException
     */
    public Person ermittlePersonViaSchluessel(int id) throws RemoteException {
        return personMapper.findeViaSchluessel(id);
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.415663A0-2478-8DFE-CE0C-0AE9BAC4A474]
    // </editor-fold>
    /**
     * Methode, um alle vorhandenen Kalender zu ermitteln. 
     * 
     * Bei dieser Methode werden die entsprechenden
     * Daten ungefiltert aus der Datenbank geholt und ausgegeben.
     *
     * @return  Vector<Kalender>    mit allen Kalendern.
     */
    public Vector<Kalender> ermitlleAlleKalender() {
        Vector<Kalender> kalenders = kalenderMapper.findeAlle();

        for (Kalender kalender : kalenders) {
            try {
                kalender.setZugriffsberechtigteId(this.kalenderZugriffMapper.
                        findeViaKalender(kalender.getKalenderId()));
            } catch (RemoteException ex) {
                Logger.getLogger(GruppenkalenderVerwaltungImpl.class.getName()).
                        log(Level.SEVERE, null, ex);
            }
        }

        return kalenders;
    }

    /**
     * Methode, um alle vorhandenen Termine von Person X zu ermitteln.
     * Bei dieser Methode werden personenspezifische Daten
     * aus der Datenbank geholt und ausgegeben.
     *
     * @param   person
     * @return  Vector<Kalender>    mit allen Kalendern von Person
     */
    public Vector<Kalender> ermittleAlleKalenderVonPerson(Person person) throws
            RemoteException {

        Vector<Kalender> kalenders = kalenderMapper.findeAlle();

        Vector<Kalender> nichtAnzuzeigendeTermine = new Vector<Kalender>();


        for (Kalender kalender : kalenders) {

            kalender.setZugriffsberechtigteId(kalenderZugriffMapper.
                    findeViaKalender(
                    kalender.getKalenderId()));

            /**
             * Prüfen, ob die Person weder Besitzer noch Teilnehmer ist.
             */
            if (((kalender.getBesitzerId() != person.getPersonId()) &&
                    (!kalender.getZugriffsberechtigteId().contains(person.
                    getPersonId())))) {
                nichtAnzuzeigendeTermine.add(kalender);
                continue;
            }
        }

        for (Kalender kalender : nichtAnzuzeigendeTermine) {
            kalenders.remove(kalender);
        }


        return kalenders;
    }

    /**
     * Ermittelt die Kalender anhand einer übergebener id.
     *
     * @param   id
     * @return  Kalender mit übergebener id.
     */
    public Kalender ermittleKalenderViaSchluessel(int id) throws RemoteException {
        return kalenderMapper.findeViaSchluessel(id);
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.33338000-BBC9-EDDB-C664-90D5784A37CB]
    // </editor-fold>
    /**
     * Methode, um alle vorhandenen Kategorien zu ermitteln. 
     *
     * Bei dieser Methode werden ungefilterte
     * Daten aus der Datenbank geholt und ausgegeben.
     *
     * @return  Vector<Kategorie>   mit allen Kategorien
     */
    public Vector<Kategorie> ermittleAlleKategorien() throws RemoteException {
        return kategorieMapper.findeAlle();
    }

    /**
     * Ermittelt die Kategorie anhand einer übergebenen id.
     * 
     * @param   id
     * @return  Kategorie mit übergebener id.
     * @throws  RemoteException
     */
    public Kategorie ermittleKategorieViaSchluessel(int id)
            throws RemoteException {
        return kategorieMapper.findeViaSchluessel(id);
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.4795B518-007F-A4E7-417B-D7B9C54C99C2]
    // </editor-fold>
    /**
     * Methode, um alle vorhandenen Termine zu ermitteln. 
     * 
     * Bei dieser Methode werden ungefilterte
     * Daten aus der Datenbank geholt und ausgegeben.
     *
     * @return Vector<Termin> mit allen Terminen.
     */
    public Vector<Termin> ermittleAlleTermine() throws RemoteException {
        Vector<Termin> termine = terminMapper.findeAlle();

        Vector<Termin> anzugzeigendeTermine = new Vector<Termin>();

        for (Termin termin : termine) {
            /**
             * Prüfen, ob Termin ein Alarm ist.
             */
            if (alarmMapper.findeViaSchluessel(termin.getId()) == null) {
                anzugzeigendeTermine.add(termin);

                Kalendereintrag k = kalendereintragMapper.findeViaSchluessel(
                        termin.getId());
                termin.setStart(k.getStart());
                termin.setEnde(k.getEnde());
                termin.setTitel(k.getTitel());
                termin.setOrt(k.getOrt());
                termin.setBeschreibung(k.getBeschreibung());
                termin.setKategorieId(k.getKategorieId());
                termin.setKalenderId(k.getKalenderId());
                termin.setErstellerId(k.getErstellerId());

                Vector<Alarm> alarme = alarmMapper.findeViaGueltigFuer(termin.
                        getId());
                for (Alarm a : alarme) {
                    k = kalendereintragMapper.findeViaSchluessel(a.getId());
                    if (k.getErstellerId() == termin.getErstellerId()) {
                        termin.setErinnerungId(a.getId());
                    }
                }

                termin.setTeilnehmerIds(terminTeilnahmeMapper.findeViaTermin(
                        termin.getId()));
            }
        }

        Collections.sort(anzugzeigendeTermine, new Comparator() {

            public int compare(Object o1, Object o2) {
                Termin t1 = (Termin) o1;
                Termin t2 = (Termin) o2;
                try {
                    return t1.getStart().compareTo(t2.getStart());
                } catch (RemoteException ex) {
                    Logger.getLogger(
                            GruppenkalenderVerwaltungImpl.class.getName()).
                            log(Level.SEVERE, null, ex);
                    return 0;
                }
            }
        });

        return anzugzeigendeTermine;
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.9598F755-D17E-F2CF-5855-389CA5C97F16]
    // </editor-fold>
    /**
     * Methode, um alle vorhandenen Termine von Person X zu ermitteln. 
     * Bei dieser Methode werden personenspezifische Daten
     * aus der Datenbank geholt und ausgegeben.
     *
     * @param person
     * @return Vector<Termin> mit allen Terminen von übergebener Person
     */
    public Vector<Termin> ermittleAlleTermineVonPerson(Person person) throws
            RemoteException {
        Vector<Termin> termine = terminMapper.findeAlle();

        Vector<Termin> anzuzeigendeTermine = new Vector<Termin>();


        for (Termin termin : termine) {

            Kalendereintrag k = kalendereintragMapper.findeViaSchluessel(
                    termin.getId());
            termin.setTeilnehmerIds(terminTeilnahmeMapper.findeViaTermin(
                    termin.getId()));

            /**
             * Prüfen, ob es ein Alarm ist,
             * oder die Person entweder Besitzer oder Teilnehmer ist.
             */
            if (alarmMapper.findeViaSchluessel(termin.getId()) == null) {
                if (k.getErstellerId() == person.getPersonId() || termin.
                        getTeilnehmerIds().contains(person.getPersonId())) {
                    anzuzeigendeTermine.add(termin);

                    termin.setStart(k.getStart());
                    termin.setEnde(k.getEnde());
                    termin.setTitel(k.getTitel());
                    termin.setOrt(k.getOrt());
                    termin.setBeschreibung(k.getBeschreibung());
                    termin.setKategorieId(k.getKategorieId());
                    termin.setKalenderId(k.getKalenderId());
                    termin.setErstellerId(k.getErstellerId());

                    Vector<Alarm> alarme = alarmMapper.findeViaGueltigFuer(
                            termin.getId());
                    for (Alarm a : alarme) {
                        k = kalendereintragMapper.findeViaSchluessel(a.getId());
                        if (k.getErstellerId() == person.getPersonId()) {
                            termin.setErinnerungId(a.getId());
                        }
                    }
                }
            }
        }

        Collections.sort(anzuzeigendeTermine, new Comparator() {

            public int compare(Object o1, Object o2) {
                Termin t1 = (Termin) o1;
                Termin t2 = (Termin) o2;
                try {
                    return t1.getStart().compareTo(t2.getStart());
                } catch (RemoteException ex) {
                    Logger.getLogger(
                            GruppenkalenderVerwaltungImpl.class.getName()).
                            log(Level.SEVERE, null, ex);
                    return 0;
                }
            }
        });

        return anzuzeigendeTermine;
    }

    /**
     * Ermittelt einen Termin anhand der übergebenen id.
     *
     * @param   id
     * @return  Termin
     * @throws  RemoteException
     */
    public Termin ermittleTerminViaSchluessel(int id) throws RemoteException {
        Kalendereintrag k = kalendereintragMapper.findeViaSchluessel(id);
        Termin termin = terminMapper.findeViaSchluessel(id);

        termin.setStart(k.getStart());
        termin.setEnde(k.getEnde());
        termin.setTitel(k.getTitel());
        termin.setOrt(k.getOrt());
        termin.setBeschreibung(k.getBeschreibung());
        termin.setKategorieId(k.getKategorieId());
        termin.setErstellerId(k.getErstellerId());
        termin.setKalenderId(k.getKalenderId());

        return termin;
    }

    /**
     * Ermittelt die Termin-Id anhand einer Folgetermin-Id.
     * @param   id
     * @return  Termin
     * @throws  RemoteException
     */
    public int ermittleTerminIdViaFolgetermin(int id) throws RemoteException {
        return terminMapper.findeViaFolgetermin(id).getId();
    }

    // <editor-fold defaultstate="collapsed" desc=" UML Marker "> 
    // #[regen=yes,id=DCE.AB8D9539-D4D3-0E5D-72CD-84D52496A9B4]
    // </editor-fold>
    /**
     * Methode, um alle vorhandenen Alarme zu ermitteln. 
     * Bei dieser Methode werden ungefilterte
     * Daten aus der Datenbank geholt und ausgegeben.
     *
     * @return  Vector<Alarm>   mit allen Alarmen.
     */
    public Vector<Alarm> ermittleAlleAlarme() throws RemoteException {
        Vector<Alarm> alarme = alarmMapper.findeAlle();

        for (Alarm alarm : alarme) {
            Termin t = terminMapper.findeViaSchluessel(
                    alarm.getId());
            alarm.setFolgeterminId(t.getFolgeterminId());

            Kalendereintrag k = kalendereintragMapper.findeViaSchluessel(
                    alarm.getId());
            alarm.setStart(k.getStart());
            alarm.setEnde(k.getEnde());
            alarm.setTitel(k.getTitel());
            alarm.setOrt(k.getOrt());
            alarm.setBeschreibung(k.getBeschreibung());
            alarm.setKategorieId(k.getKategorieId());
            alarm.setKalenderId(k.getKalenderId());
            alarm.setErstellerId(k.getErstellerId());
        }

        Collections.sort(alarme, new Comparator() {

            public int compare(Object o1, Object o2) {
                Alarm a1 = (Alarm) o1;
                Alarm a2 = (Alarm) o2;
                try {
                    return a1.getStart().compareTo(a2.getStart());
                } catch (RemoteException ex) {
                    Logger.getLogger(
                            GruppenkalenderVerwaltungImpl.class.getName()).
                            log(Level.SEVERE, null, ex);
                    return 0;
                }
            }
        });

        return alarme;
    }

    /**
     * Ermittelt alle Alarme einer angegebenen Person.
     *
     * @param   person
     * @return  Vector<Alarm>       Alarme einer Person.
     * @throws  RemoteException
     */
    public Vector<Alarm> ermittleAlleAlarmeVonPerson(Person person) throws
            RemoteException {
        Vector<Alarm> alarme = alarmMapper.findeAlle();

        Vector<Alarm> anzuzeigendeAlarme = new Vector<Alarm>();

        for (Alarm alarm : alarme) {

            Kalendereintrag k = kalendereintragMapper.findeViaSchluessel(alarm.
                    getId());
            // Prüfen, ob die Person Besitzer ist.
            if (k.getErstellerId() == person.getPersonId()) {

                anzuzeigendeAlarme.add(alarm);

                alarm.setStart(k.getStart());
                alarm.setEnde(k.getEnde());
                alarm.setTitel(k.getTitel());
                alarm.setOrt(k.getOrt());
                alarm.setBeschreibung(k.getBeschreibung());
                alarm.setKategorieId(k.getKategorieId());
                alarm.setKalenderId(k.getKalenderId());
                alarm.setErstellerId(k.getErstellerId());
            }

        }

        Collections.sort(anzuzeigendeAlarme, new Comparator() {

            public int compare(Object o1, Object o2) {
                Alarm a1 = (Alarm) o1;
                Alarm a2 = (Alarm) o2;
                try {
                    return a1.getStart().compareTo(a2.getStart());
                } catch (RemoteException ex) {
                    Logger.getLogger(
                            GruppenkalenderVerwaltungImpl.class.getName()).
                            log(Level.SEVERE, null, ex);
                    return 0;
                }
            }
        });

        return anzuzeigendeAlarme;
    }

    /**
     * Ermittelt alle Alarme anhand der übergebenen Parameter.
     *
     * Die Parameter dienen als Filter, die null sein können.
     * Sind die Parameter nicht null gilt Folgendes:
     *
     * Die übergebene Person muss entweder Ersteller des Alarms sein.
     * Die ID des übergebenen Kalenders muss der Kalender-Id des Alarms
     * entsprechen.
     * Die ID der übergebenen Kategorie muss der Kategorie-Id des Alarms
     * entsprechen.
     *
     * Der Alarm muss zwischen dem übergebenen von- und bis-Zeitpunkt liegen.
     *
     * @param person
     * @param kalender
     * @param kategorie
     * @param von
     * @param bis
     * @return Vector<Alarm> mit allen Alarmen.
     * @throws RemoteException
     */
    public Vector<Alarm> ermittleAlleAlarmeVia(Person person, Kalender kalender,
            Kategorie kategorie, Timestamp von, Timestamp bis) throws
            RemoteException {
        Vector<Alarm> alarme = new Vector<Alarm>();

        Vector<Alarm> anzuzeigendeAlarme = new Vector<Alarm>();

        if (person != null) {
            alarme = this.ermittleAlleAlarmeVonPerson(person);
        } else {
            alarme = this.ermittleAlleAlarme();
        }

        for (Alarm alarm : alarme) {

            boolean anzeigen = false;

            if (kalender != null) {
                if (kalender.getKalenderId() == alarm.getKalenderId()) {
                    anzeigen = true;
                }
            }

            if (kategorie != null) {
                if (kategorie.getKategorieId() == alarm.getKategorieId()) {
                    anzeigen = true;
                }
            }

            if (kalender == null && kategorie == null) {
                anzeigen = true;
            }

            if (von != null && bis == null) {
                if (von.after(alarm.getStart())) {
                    /**
                     * Termin liegt (komplett) VOR dem von-Timestamp.
                     * Also NICHT anzeigen.
                     */
                    anzeigen = false;
                }
            } else if (bis != null && von == null) {
                if (bis.before(alarm.getStart())) {
                    /**
                     * Termin liegt komplett NACH dem bis-Timestamp.
                     * Also NICHT anzeigen.
                     */
                    anzeigen = false;
                }
            } else if (von != null && bis != null) {
                if (von.after(alarm.getStart()) ||
                        (bis.before(alarm.getStart()))) {
                    /**
                     * Termin liegt entweder komplett VOR dem von-Timestamp,
                     * oder komplett NACH dem bis-Timestamp.
                     * Also NICHT anzeigen.
                     */
                    anzeigen = false;
                }
            }

            if (anzeigen) {
                anzuzeigendeAlarme.add(alarm);
            }
        }

        Collections.sort(anzuzeigendeAlarme, new Comparator() {

            public int compare(Object o1, Object o2) {
                Alarm a1 = (Alarm) o1;
                Alarm a2 = (Alarm) o2;
                try {
                    return a1.getStart().compareTo(a2.getStart());
                } catch (RemoteException ex) {
                    Logger.getLogger(
                            GruppenkalenderVerwaltungImpl.class.getName()).
                            log(Level.SEVERE, null, ex);
                    return 0;
                }
            }
        });

        return anzuzeigendeAlarme;
    }

    /**
     * Ermittelt einen Alarm anhand einer übergebenen Id.
     * 
     * @param   id
     * @return  Alarm   der via Schlüssel ermittelt wurde
     * @throws  RemoteException
     */
    public Alarm ermittleAlarmViaSchluessel(int id) throws RemoteException {
        Alarm alarm = alarmMapper.findeViaSchluessel(id);

        if (alarm == null) {
            return null;
        }

        Termin t = terminMapper.findeViaSchluessel(
                alarm.getId());
        alarm.setFolgeterminId(t.getFolgeterminId());

        Kalendereintrag k = kalendereintragMapper.findeViaSchluessel(
                alarm.getId());
        alarm.setStart(k.getStart());
        alarm.setEnde(k.getEnde());
        alarm.setTitel(k.getTitel());
        alarm.setOrt(k.getOrt());
        alarm.setBeschreibung(k.getBeschreibung());
        alarm.setKategorieId(k.getKategorieId());
        alarm.setKalenderId(k.getKalenderId());
        alarm.setErstellerId(k.getErstellerId());

        return alarm;
    }

    /**
     * Prüft, ob die angegebene Termin-Id eine Wiederholung ist.
     *
     * @param   id
     * @return  true oder false
     * @throws  RemoteException
     */
    public boolean istWiederholung(int id) throws RemoteException {
        if (wiederholungMapper.findeViaSchluessel(id) != null) {
            return true;
        }
        return false;
    }

    /**
     * Ermittelt den Abstand zwischen den Wiederholung des übergebenen Termins.
     *
     * @param   termin
     * @return  int     Abstand zwischen den Wiederholungen.
     * @throws  RemoteException
     */
    public int ermittleAbstandWiederholung(Termin termin) throws RemoteException {
        int[] abstand = {0, 0, 0, 0};

        Termin tempTermin = termin;

        while (istWiederholung(tempTermin.getId())) {
            tempTermin = terminMapper.findeViaFolgetermin(tempTermin.getId());
        }

        Kalendereintrag tempKalendereintrag = kalendereintragMapper.
                findeViaSchluessel(tempTermin.getId());

        while (tempTermin.getFolgeterminId() != 0) {
            Timestamp timestamp1 = tempKalendereintrag.getStart();

            tempTermin = terminMapper.findeViaSchluessel(tempTermin.
                    getFolgeterminId());
            tempKalendereintrag = kalendereintragMapper.findeViaSchluessel(
                    tempTermin.getId());
            Timestamp timestamp2 = tempKalendereintrag.getStart();

            long differenz = timestamp2.getTime() - timestamp1.getTime();

            Calendar c = Calendar.getInstance();
            int[] tempFields = {Calendar.DAY_OF_WEEK, Calendar.WEEK_OF_MONTH,
                Calendar.MONTH, Calendar.YEAR};
            long[] differenzCompare = new long[4];

            for (int i = 0; i < tempFields.length; i++) {
                c.setTime(timestamp1);
                c.add(tempFields[i], 1);
                differenzCompare[i] = new Timestamp(c.getTime().getTime()).
                        getTime() - timestamp1.getTime();

                if (differenz == differenzCompare[i]) {
                    abstand[i]++;
                }
            }
        }

        int max = 0;
        int result = DialogTermin.WIEDERHOLUNG_KEINE;

        if (abstand[0] > max) {
            max = abstand[0];
            result = DialogTermin.WIEDERHOLUNG_TAG;
        }
        if (abstand[1] > max) {
            max = abstand[1];
            result = DialogTermin.WIEDERHOLUNG_WOCHE;
        }
        if (abstand[2] > max) {
            max = abstand[2];
            result = DialogTermin.WIEDERHOLUNG_MONAT;
        }
        if (abstand[3] > max) {
            max = abstand[3];
            result = DialogTermin.WIEDERHOLUNG_JAHR;
        }

        return result;
    }

    /**
     * Ermittelt die Anzahl der Wiederholung eines übergebenen Termins.
     *
     * @param   termin
     * @return  int     Anzahl der Wiederholungen.
     * @throws  RemoteException
     */
    public int ermittleAnzahlWiederholung(Termin termin) throws RemoteException {
        int result = 0;

        Termin tempTermin = termin;

        while (istWiederholung(tempTermin.getId())) {
            tempTermin = terminMapper.findeViaFolgetermin(tempTermin.getId());
        }

        while (tempTermin.getFolgeterminId() != 0) {
            result++;
            tempTermin = terminMapper.findeViaSchluessel(tempTermin.
                    getFolgeterminId());
        }

        return result;
    }

    /**
     * Ermittelt alle Termine anhand der übergebenen Parameter.
     *
     * Die Parameter dienen als Filter, die null sein können.
     * Sind die Parameter nicht null gilt Folgendes:
     *
     * Die übergebene Person muss entweder Ersteller oder
     * Teilnehmer am Termin sein.
     * Die ID des übergebenen Kalenders muss der Kalender-Id des Termins
     * entsprechen.
     * Die ID der übergebenen Kategorie muss der Kategorie-Id des Termins
     * entsprechen.
     *
     * Der Termin muss zwischen dem übergebenen von- und bis-Zeitpunkt liegen.
     *
     * @param person
     * @param kalender
     * @param kategorie
     * @param von
     * @param bis
     * @return Vector<Termin> mit allen Terminen.
     * @throws RemoteException
     */
    public Vector<Termin> ermittleAlleTerminVia(Person person, Kalender kalender,
            Kategorie kategorie, Timestamp von, Timestamp bis) throws
            RemoteException {
        Vector<Termin> termine = new Vector<Termin>();

        Vector<Termin> anzuzeigendeTermine = new Vector<Termin>();

        if (person != null) {
            termine = this.ermittleAlleTermineVonPerson(person);
        } else {
            termine = this.ermittleAlleTermine();
        }

        for (Termin termin : termine) {

            boolean anzeigen = false;

            if (kalender != null) {
                if (kalender.getKalenderId() == termin.getKalenderId()) {
                    anzeigen = true;
                }
            }

            if (kategorie != null) {
                if (kategorie.getKategorieId() == termin.getKategorieId()) {
                    anzeigen = true;
                }
            }

            if (kalender == null && kategorie == null) {
                anzeigen = true;
            }

            if (von != null && bis == null) {
                if (von.after(termin.getStart()) &&
                        von.after(termin.getEnde())) {
                    /**
                     * Termin liegt (komplett) VOR dem von-Timestamp.
                     * Also NICHT anzeigen.
                     */
                    anzeigen = false;
                }
            } else if (bis != null && von == null) {
                if (bis.before(termin.getStart()) &&
                        bis.before(termin.getEnde())) {
                    /**
                     * Termin liegt komplett NACH dem bis-Timestamp.
                     * Also NICHT anzeigen.
                     */
                    anzeigen = false;
                }
            } else if (von != null && bis != null) {
                if ((von.after(termin.getStart()) &&
                        von.after(termin.getEnde())) || (bis.before(termin.
                        getStart()) && bis.before(termin.getEnde()))) {
                    /**
                     * Termin liegt entweder komplett VOR dem von-Timestamp,
                     * oder komplett NACH dem bis-Timestamp.
                     * Also NICHT anzeigen.
                     */
                    anzeigen = false;
                }
            }

            if (anzeigen) {
                anzuzeigendeTermine.add(termin);
            }
        }

        Collections.sort(anzuzeigendeTermine, new Comparator() {

            public int compare(Object o1, Object o2) {
                Termin t1 = (Termin) o1;
                Termin t2 = (Termin) o2;
                try {
                    return t1.getStart().compareTo(t2.getStart());
                } catch (RemoteException ex) {
                    Logger.getLogger(
                            GruppenkalenderVerwaltungImpl.class.getName()).
                            log(Level.SEVERE, null, ex);
                    return 0;
                }
            }
        });

        return anzuzeigendeTermine;
    }
}
